package com.nulldev.util.web.HttpServer3.extensions.nCaptcha.captchas.auto;

import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.io.file.FileUtil;
import com.nulldev.util.languages.json.uniapi.UniJsonValue;
import com.nulldev.util.security.hashAPI.Hashes;
import com.nulldev.util.security.hashAPI.Hashes.Hashables;
import com.nulldev.util.web.HttpServer3.Response;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.user.User;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.user.UserInfoType;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.backend.util.UUIDCookieLoader;
import com.nulldev.util.web.HttpServer3.extensions.nCaptcha.captchas.auto.math.MathChallengeGenerator.MathChallengeContext;
import com.nulldev.util.web.HttpServer3.legacyPages.v1.RequestType;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3;

public class RequestAutoCaptchaPayload extends HttpPage3 {

	public RequestAutoCaptchaPayload() {
		super("/captcha/request_auto", true);
		super.setCachingMethod(CachingMethod.NO_CACHE);
	}

	private static final String JSON_MIME = "application/json; charset=utf-8";
	private static final byte[] PAYLOAD_BYTES = FileUtil.getResourceBytes(RequestAutoCaptchaPayload.class, "payload.js");

	@SuppressWarnings("resource")
	@Override
	public Response onRequest(final Request request) {
		if (!request.getType().equals(RequestType.POST)) {
			return new Response(405);
		}

		if (!request.hasInputStream()) {
			return new Response(411);
		}

		final String body = toString(request.getInputStream());

		if (body == null || !(body.startsWith("{") && body.endsWith("}"))) {
			return new Response(406);
		}

		final UniJsonValue context = UniJsonValue.parse(body);

		if (context == null || context.isNull()) {
			return new Response(503);
		}

		final User user = UUIDCookieLoader.tryUserFromRequest(request);
		final UniJsonValue obj = UniJsonValue.object(7);

		if (context.bool("gyro")) {
			user.putUserInfo(UserInfoType.USER_INFO_V4_GRYO_CHALLENGE_SUPPORTED, true);
		}

		final MathChallengeContext ctx = user.getMathChallengeContext();
		obj.add("payload", user.encryptPayload(PAYLOAD_BYTES));
		obj.add("uuid", user.uuid());
		obj.add("key", user.key());
		obj.add("cipher", user.getCipher().format());
		obj.add("math_payload", user.encryptPayload(ctx.getPayload()));
		if (user.hasInfoObject(UserInfoType.USER_INFO_V3_SAFETY_HASH)) {
			obj.add("safety_hash", user.getUserInfoObject(UserInfoType.USER_INFO_V3_SAFETY_HASH));
		} else {
			final String str = StringsUtil.randomString(64);
			final String hashed = (String) Hashes.get(Hashables.SHA256).hash(str.getBytes());
			user.putUserInfo(UserInfoType.USER_INFO_V3_SAFETY_HASH, hashed);
			obj.add("safety_hash", str);
		}
		return new Response(200, obj, obj).setCustomMime(JSON_MIME).header("Set-Cookie", UUIDCookieLoader.makeCookieFromUUID(user));
	}
}
